#include "book.h"

#include <utility>
#include <cstring>

/*
 * Constructors & destructors
 */

Book::Book() : name(""), author(""), publish_year(0) {

}

Book::Book(const char *name,
           const char *author,
           int publish_year) : name(name), author(author),
                               publish_year(publish_year) {

}

Book::Book(std::string name,
           std::string author,
           int publish_year) : name(name), author(author),
    publish_year(publish_year) {

}

Book::Book(const Book &other) {
    this->name = other.name;
    this->author = other.author;
    this->publish_year = other.publish_year;
}

Book::~Book() {}

/*
 * Setters & getters
 */

void Book::setName(const char *name) {
    this->name = name;
}

void Book::setName(std::string name) {
    this->name = name;
}

void Book::setAuthor(const char *author) {
    this->author = author;
}

void Book::setAuthor(std::string author) {
    this->author = author;
}

void Book::setPublishYear(int publish_year) {
    this->publish_year = publish_year;
}

void Book::setBook(const char *name, const char *author, int publish_year) {
    this->name = name;
    this->author = author;
    this->publish_year = publish_year;
}

void Book::setBook(std::string name, std::string author, int publish_year) {
    this->name = name;
    this->author = author;
    this->publish_year = publish_year;
}

char * Book::getName() {
    char *res = new char[this->name.size()];
    std::strcpy(res, this->name.c_str());
    return res;
}

char * Book::getAuthor() {
    char *res = new char[this->author.size()];
    std:strcpy(res, this->author.c_str());
    return res;
}

int Book::getPublishYear() {
    return this->publish_year;
}

/*
 * Overloads
 */

Book & Book::operator=(const Book &other) {
    if(this == &other) return *this;

    this->name = other.name;
    this->author = other.author;
    this->publish_year = other.publish_year;
    return *this;
}

Book & Book::operator=(Book &&other) noexcept {
    if(this == &other) return *this;

    this->name = std::exchange(other.name, std::string(""));
    this->author = std::exchange(other.author, std::string(""));
    this->publish_year = std::exchange(other.publish_year, 0);
    return *this;
}

std::ostream & operator<<(std::ostream &os, const Book &book) {
    os << "===\n" << book.name << "\n" <<
                     book.author << "\n" <<
                     book.publish_year << "\n===\n";

    return os;
}

std::istream & operator>>(std::istream &is, Book &book) {
    std::string inp;
    std::string name, author;
    int publish_year;

    for(;;) {
        std::getline(is, inp);
        if(!strchr(inp.c_str(), ' ') && !strchr(inp.c_str(), '\t') &&
           !strchr(inp.c_str(), '\v') && !strchr(inp.c_str(), '\r') &&
           !inp.empty())
           break;
    }
    if(strcmp(inp.c_str(), "===")) {
        return is;
    }

    try {
        std::getline(is, name);
        std::getline(is, author);
        std::getline(is, inp);
        publish_year = std::stoi(inp);
    }
    catch(const std::exception &e) {
        return is;
    }

    std::getline(is, inp);
    if(strcmp(inp.c_str(), "===")) {
        return is;
    }

    book.setBook(name, author, publish_year);
    return is;
}
